package com.basic.business.redis.server;

import com.basic.business.common.constants.Constants;
import com.basic.business.common.redis.RedisCacheUtils;
import com.basic.business.common.utils.SpringUtils;
import com.basic.business.common.utils.StringUtils;
import com.basic.business.log.service.ITOrdersLogService;
import com.basic.business.order.domain.TOrdersDetail;
import com.basic.business.order.domain.TOrdersMain;
import com.basic.business.order.domain.TOrdersMerge;
import com.basic.business.redis.domain.TOrdersDetailRedis;
import com.basic.business.redis.domain.TOrdersMainRedis;
import com.basic.business.redis.domain.TOrdersMergeRedis;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单信息同步到Redis中
 *
 * @author zhaoxy_jn@163.com
 */
@Slf4j
@Component
public class SyncOrdersToRedisServer {

    /**
     * 入口
     * @param ordersMains 订单信息
     */
    public static void init(List<TOrdersMain> ordersMains){
        try {
            ordersMains.forEach(ordersMain -> {
                // 从Redis中获取
                TOrdersMainRedis ordersMainRedis = RedisCacheUtils.getCacheObject(Constants.ORDERS_REDIS_KEY + ordersMain.getSid());
                if (Objects.isNull(ordersMainRedis)) { // 新增Redis信息
                    addOrdersMainRedis(ordersMain);
                } else { // 更新Redis信息
                    updateOrdersMainRedis(ordersMain, ordersMainRedis);
                }
            });
        }catch (Exception e) {
            log.error("【订单信息同步到Redis中失败】", e);
        }
    }

    /**
     * 新增Redis信息
     */
    public static void addOrdersMainRedis(TOrdersMain ordersMain){
        TOrdersMainRedis ordersMainRedis = new TOrdersMainRedis();
        copyClass(ordersMain,ordersMainRedis);
        // 写入Redis
        RedisCacheUtils.setCacheObject(Constants.ORDERS_REDIS_KEY + ordersMain.getSid(),ordersMainRedis);
        // 写日志
        addOrdersLog(ordersMain);
    }

    /**
     * 新增订单写日志
     */
    public static void addOrdersLog(TOrdersMain ordersMain){
        List<TOrdersMerge> mergeList = ordersMain.getMergeList();
        // 主系统订单
        long mainSid = ordersMain.getSid();
        if (mergeList.isEmpty()) { // 单一订单
            // 系统订单号
            long sid = ordersMain.getSid();
            // 下单时间
            long created = ordersMain.getCreated();
            SpringUtils.getBean(ITOrdersLogService.class).insert(mainSid, sid, "同步下载订单", created);
        } else { // 若是合并订单，则分别写日志
            mergeList.forEach(ordersMerge -> {
                // 系统订单号
                long sid = ordersMerge.getMergeSid();
                // 下单时间
                long created = ordersMerge.getCreated();
                SpringUtils.getBean(ITOrdersLogService.class).insert(mainSid, sid, "同步下载订单", created);
            });
        }
    }

    /**
     * 更新Redis信息
     */
    public static void updateOrdersMainRedis(TOrdersMain ordersMain, TOrdersMainRedis ordersMainRedis){
        // 更新订单写日志
//        updateOrdersLog(ordersMain,ordersMainRedis);
        // 比较变化
        compareOrders(ordersMain,ordersMainRedis);
        // 复制对象属性
        copyClass(ordersMain,ordersMainRedis);
        // 写入Redis
        RedisCacheUtils.setCacheObject(Constants.ORDERS_REDIS_KEY + ordersMain.getSid(),ordersMainRedis);

    }

    /**
     * 更新订单写日志
     */
    public static void updateOrdersLog(TOrdersMain ordersMain, TOrdersMainRedis ordersMainRedis){
        // 主系统订单号
        long mainSid = ordersMain.getSid();
        /*
          判断是否需要写新增订单的日志
          若ordersMain中mergeList不为空，且mergeList中的sid未在ordersMainRedis中，则需要写新增订单的日志
         */
        // Redis中的sid集合
        Set<Long> detailRedisSids = ordersMainRedis.getDetailList().stream().map(TOrdersDetailRedis::getDetailSid).collect(Collectors.toSet());
        // API中的sid集合
        Set<Long> detailsSids = ordersMain.getDetailList().stream().map(TOrdersDetail::getDetailSid).collect(Collectors.toSet());
        // 比较两个set的差值
        Set<Long> diffSids = detailsSids.stream().filter(sid -> !detailRedisSids.contains(sid)).collect(Collectors.toSet());
        if (!diffSids.isEmpty()) {
            // 将API中的订单详情转换为Map以提高查找效率
            Map<Long, TOrdersDetail> detailMap = ordersMain.getDetailList().stream()
                    .collect(Collectors.toMap(TOrdersDetail::getDetailSid, detail -> detail, (existing, replacement) -> existing, LinkedHashMap::new));

            diffSids.forEach(sid -> {
                TOrdersDetail ordersDetail = detailMap.get(sid);
                if (ordersDetail != null) {
                    SpringUtils.getBean(ITOrdersLogService.class).insert(mainSid, sid, "新增订单", ordersDetail.getCreated());
                }
            });
        }
    }

    /**
     * 比较订单信息变化
     */
    public static void compareOrders(TOrdersMain ordersMain,TOrdersMainRedis ordersMainRedis){
        String beforeContent = "同步修改订单信息：";
        StringBuilder content = new StringBuilder(beforeContent);

        // 比较运单号
        if (ordersMain.getOutSid() != null && !StringUtils.equals(ordersMain.getOutSid(), ordersMainRedis.getOutSid())){
            String outSidChange = StringUtils.format("运单号【{}】->【{}】", ordersMainRedis.getOutSid(), ordersMain.getOutSid());
            content.append(outSidChange).append(";");
        }

        // 将API中的订单详情转换为Map以提高查找效率
        Map<Long, TOrdersDetailRedis> detailRedisMap = ordersMainRedis.getDetailList().stream()
                .collect(Collectors.toMap(TOrdersDetailRedis::getDetailSid, detail -> detail,  (existing, replacement) -> existing));

        // 比较订单明细中的状态和卖家备注
        for (TOrdersDetail ordersDetail : ordersMain.getDetailList()) {
            TOrdersDetailRedis orderDetailRedis = detailRedisMap.get(ordersDetail.getDetailSid());
            if (!Objects.isNull(orderDetailRedis)) {
                // 比对状态
                if (!StringUtils.equals(orderDetailRedis.getSysStatus(), ordersDetail.getSysStatus())){
                    String sysStatusChange = StringUtils.format("状态【{}】->【{}】", orderDetailRedis.getSysStatus(), ordersDetail.getSysStatus());
                    content.append(sysStatusChange).append(";");
                }
                // 比对卖家备注
                if (!StringUtils.equals(orderDetailRedis.getSellerMemo(), ordersDetail.getSellerMemo())){
                    String sellerMemoChange = StringUtils.format("卖家备注【{}】->【{}】", orderDetailRedis.getSellerMemo(), ordersDetail.getSellerMemo());
                    content.append(sellerMemoChange).append(";");
                }
            }
        }

        if (content.length() > beforeContent.length()) {
            // 删除最后一个分号
            content.deleteCharAt(content.length() - 1);
            // 写日志
            SpringUtils.getBean(ITOrdersLogService.class).insert(ordersMain.getSid(), ordersMain.getSid(), content.toString(), 0);
        }

    }


    /**
     * 对象拷贝
     */
    public static void copyClass(TOrdersMain ordersMain,TOrdersMainRedis ordersMainRedis){
        // 复制主订单属性
        BeanUtils.copyProperties(ordersMain,ordersMainRedis);
        // 复制子订单属性
        List<TOrdersDetailRedis> detailsToAdd = new ArrayList<>();
        // 获取API中的子订单
        List<TOrdersDetail> sourceDetails = Optional.ofNullable(ordersMain.getDetailList()).orElse(Collections.emptyList());
        // 获取Redis中的子订单
        List<TOrdersDetailRedis> redisDetails = Optional.ofNullable(ordersMainRedis.getDetailList()).orElse(new ArrayList<>());

        // 使用 Map 提高查找效率
        Map<Long, TOrdersDetailRedis> redisDetailsMap = new HashMap<>();
        for (TOrdersDetailRedis detail : redisDetails) {
            redisDetailsMap.put(detail.getId(), detail);
        }
        for (TOrdersDetail ordersDetail : sourceDetails) {
            if (StringUtils.equals(ordersDetail.getIsGift(), "N")) {
                TOrdersDetailRedis ordersDetailRedis = new TOrdersDetailRedis();
                BeanUtils.copyProperties(ordersDetail, ordersDetailRedis);

                Long targetId = ordersDetail.getId();
                TOrdersDetailRedis existingDetail = redisDetailsMap.get(targetId);
                if (existingDetail != null) { // 如果存在，则更新属性
                    boolean autoProcessed = existingDetail.isAutoProcessed();
                    ordersDetailRedis.setAutoProcessed(autoProcessed);
                    // 使用 BeanUtils 更新现有对象的属性
                    BeanUtils.copyProperties(ordersDetailRedis, existingDetail);
                } else { // 如果不存在，则添加到列表
                    detailsToAdd.add(ordersDetailRedis);
                }
            }
        }

        if (!detailsToAdd.isEmpty()) {
            redisDetails.addAll(detailsToAdd);
        }

        // 复制合并订单属性
        ordersMainRedis.getMergeList().removeIf(ordersMergeRedis -> ordersMain.getMergeList().stream().anyMatch(ordersMerge -> ordersMerge.getMergeSid() == ordersMergeRedis.getMergeSid()));
        ordersMain.getMergeList().forEach(ordersMerge -> {
            TOrdersMergeRedis ordersMergeRedis = new TOrdersMergeRedis();
            BeanUtils.copyProperties(ordersMerge,ordersMergeRedis);
            ordersMainRedis.getMergeList().add(ordersMergeRedis);
        });
    }

}
